www.gusucode.com > VC++ 树节点动态添加插入-源码程序 > VC++ 树节点动态添加插入-源码程序/code/NoteDlg.cpp
//Download by http://www.NewXing.com // NoteDlg.cpp : implementation file // #include "stdafx.h" #include "Note.h" #include "NoteDlg.h" #include "zip.h" #include "unzip.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CNoteDlg dialog CNoteDlg::CNoteDlg(CWnd* pParent /*=NULL*/) : CDialog(CNoteDlg::IDD, pParent) { //{{AFX_DATA_INIT(CNoteDlg) //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CNoteDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CNoteDlg) DDX_Control(pDX, IDC_TREE, m_wndTree); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CNoteDlg, CDialog) //{{AFX_MSG_MAP(CNoteDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_ADDNEW, OnAddnew) ON_COMMAND(ID_OPEN, OnOpenFile) ON_COMMAND(ID_SAVEAS, OnSaveAs) ON_COMMAND(ID_ABOUT, OnAbout) ON_COMMAND(ID_NEW, OnNew) ON_NOTIFY(TVN_SELCHANGED, IDC_TREE, OnSelchangedTree) ON_BN_CLICKED(IDOK, OnOk) ON_WM_CLOSE() ON_COMMAND(ID_EXIT, OnExit) ON_COMMAND(ID_SAVE, OnSave) ON_BN_CLICKED(IDC_DEL, OnDel) ON_BN_CLICKED(IDC_RENAME, OnRename) ON_WM_DESTROY() ON_NOTIFY(TVN_ITEMEXPANDED, IDC_TREE, OnItemexpandedTree) ON_COMMAND(ID_FONT, OnFont) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CNoteDlg message handlers BOOL CNoteDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here CRect treeRect; GetDlgItem(IDC_TREE)->GetWindowRect(&treeRect); ScreenToClient(&treeRect); CRect wndRect; GetClientRect(&wndRect); CRect editRect; editRect.left=treeRect.right+10; editRect.top=treeRect.top; editRect.right=wndRect.right-10; editRect.bottom=wndRect.bottom-10; DWORD style=0; //创建编辑控件,设置字体 m_wndOwnEdit.Create(WS_CHILDWINDOW|WS_VISIBLE|WS_VSCROLL|WS_BORDER|ES_MULTILINE|ES_LEFT,editRect,this,IDC_EDIT); m_wndOwnEdit.SetMargins(5,5); //设置显示边界 m_pEditFont=new CFont(); LOGFONT lf; GetFont()->GetLogFont(&lf); m_pEditFont->CreateFontIndirect(&lf); m_wndOwnEdit.SetFont(m_pEditFont); //初始化变量 m_dwDocCount=-1; m_dwItemCount=0; m_strCurOpenFile.Empty(); m_bIsModified=FALSE; GetWindowText(m_strTitle); //获得程序刚启动时的窗口标题 //创建树控件的图像列表 m_pImgList=new CImageList(); m_pImgList->Create(16,16,ILC_COLOR8,3,5); HICON hIcon; hIcon=AfxGetApp()->LoadIcon(IDI_CLASS_CLOSE); m_pImgList->Add(hIcon); hIcon=AfxGetApp()->LoadIcon(IDI_CLASS_OPEN); m_pImgList->Add(hIcon); hIcon=AfxGetApp()->LoadIcon(IDI_DOC); m_pImgList->Add(hIcon); m_wndTree.SetImageList(m_pImgList,TVSIL_NORMAL); m_wndTree.SetTextColor(RGB(0,0,255)); //如果m_strShellFileName(由InitInstance()传递)非空,则说明程序时Shell打开的. if(!m_strShellFileName.IsEmpty()) { if(!CheckFileFormat(m_strShellFileName)) return FALSE; return OpenTree(m_strShellFileName); } return TRUE; // return TRUE unless you set the focus to a control } void CNoteDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CNoteDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CNoteDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } //按钮"新增"的响应函数,向树控件中添加新项 void CNoteDlg::OnAddnew() { // TODO: Add your control notification handler code here CNewClassDlg dlg; HTREEITEM hParentItem=m_wndTree.GetSelectedItem(); if(!hParentItem) { hParentItem=TVI_ROOT; dlg.m_bIsRaDocEnabled=FALSE; } CString strName,strText; strName.Empty(); strText.Empty(); if(dlg.DoModal()==IDOK) { strName=dlg.m_strNewClassName; strText=dlg.m_strInfo; } if(!strName.IsEmpty()) { HTREEITEM hItem=m_wndTree.InsertItem(strName,hParentItem); m_dwItemCount++; m_bIsModified=TRUE; //置文件更改标志 if(dlg.m_bIsDoc) //添加的是否是文档项 { m_dwDocCount++; m_wndTree.SetItemData(hItem,m_dwDocCount); m_wndTree.SetItemImage(hItem,2,2); if(!strText.IsEmpty()) { //把该文档项的内容写到一临时文件中 CString strTmpFileName=CreateTempFileName(); CFile file; file.Open(strTmpFileName,CFile::modeCreate|CFile::modeReadWrite); file.Write(strText,strText.GetLength()); file.Close(); DOC_INFO docInfo; docInfo.bIsNew=TRUE; docInfo.dwLength=strText.GetLength(); docInfo.dwOffset=0; //把该文档项对应的文件名定向到该临时文件 strcpy(docInfo.szFileName,strTmpFileName); m_arDoc.SetAtGrow(m_dwDocCount,docInfo);//向文档队列添加该文档信息 } else { DOC_INFO docInfo; docInfo.bIsNew=TRUE; docInfo.dwLength=0; docInfo.dwOffset=0; strcpy(docInfo.szFileName," "); m_arDoc.SetAtGrow(m_dwDocCount,docInfo); } } else m_wndTree.SetItemData(hItem,-1); m_wndTree.Expand(hParentItem,TVE_EXPAND); m_wndTree.SelectItem(hItem); } } //保存树控件中的内容到文件 // 该函数具体功能见所附的<<说明.txt>> BOOL CNoteDlg::SaveTree(CString strFileName) { HTREEITEM hWriteItem=m_wndTree.GetRootItem(); if(!hWriteItem) return FALSE; CString strTmpDocFileName=CreateTempFileName(); CString strTmpItemFileName=CreateTempFileName(); CFile tmpDocFile; CFile tmpItemFile; tmpDocFile.Open(strTmpDocFileName,CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyWrite); tmpItemFile.Open(strTmpItemFileName,CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyWrite); ITEM_INFO *pItemInfo; HGLOBAL hMemItemInfo=GlobalAlloc(GHND,sizeof(ITEM_INFO)); pItemInfo=(ITEM_INFO*)GlobalLock(hMemItemInfo); GlobalUnlock(hMemItemInfo); DOC_INFO *pDocInfo; HGLOBAL hMemDocInfo=GlobalAlloc(GHND,sizeof(DOC_INFO)); pDocInfo=(DOC_INFO*)GlobalLock(hMemDocInfo); GlobalUnlock(hMemDocInfo); DWORD dwItemData=-1; int flag=1; do{ CString str=m_wndTree.GetItemText(hWriteItem); strcpy(pItemInfo->szName,(LPCTSTR)str); pItemInfo->nFlag=flag; pItemInfo->dwOffset=0; pItemInfo->dwLength=0; pItemInfo->bIsDoc=FALSE; dwItemData=m_wndTree.GetItemData(hWriteItem); if(dwItemData!=-1) //说明是文档项 { pItemInfo->bIsDoc=TRUE; pDocInfo=&(m_arDoc.GetAt((int)dwItemData)); //获取该文档项的信息 if(pDocInfo->dwLength>0) { if(pDocInfo->bIsNew==FALSE) //如不是新插入的项,则不需压缩数据 { CFile dataFile; dataFile.Open(pDocInfo->szFileName,CFile::modeRead); pItemInfo->dwLength=pDocInfo->dwLength; pItemInfo->dwOffset=tmpDocFile.GetPosition(); dataFile.Seek(pDocInfo->dwOffset,CFile::begin); LPVOID lpBuffer; HGLOBAL hMem=GlobalAlloc(GHND,pDocInfo->dwLength+1); lpBuffer=GlobalLock(hMem); dataFile.ReadHuge(lpBuffer,pDocInfo->dwLength); //直接从源文件(应该是m_strCurOpenFile)中读取压缩数据 dataFile.Close(); tmpDocFile.WriteHuge(lpBuffer,pDocInfo->dwLength); GlobalUnlock(hMem); GlobalFree(hMem); } else //是新插入的文档项,则要压缩数据 { CString tpf; //压缩到临时文件tpf中 tpf=CreateTempFileName(); CZip zip(pDocInfo->szFileName); zip.SwapSize(tpf); CFile fl; fl.Open(tpf,CFile::modeRead|CFile::shareDenyWrite); DWORD length=fl.GetLength(); pItemInfo->dwLength=length; pItemInfo->dwOffset=tmpDocFile.GetPosition(); LPVOID lpBuffer; HGLOBAL hMem=GlobalAlloc(GHND,length); lpBuffer=GlobalLock(hMem); fl.Read(lpBuffer,length); fl.Close(); tmpDocFile.WriteHuge(lpBuffer,length); //再从文件tpf中转移到tmpFile中 DeleteFile(tpf); //删除临时文件 GlobalUnlock(hMem); GlobalFree(hMem); } tmpDocFile.Flush(); } } tmpItemFile.Write(pItemInfo,sizeof(ITEM_INFO)); //向主文件写入项信息 }while(hWriteItem=GetNextWriteItem(hWriteItem,flag)); GlobalFree(hMemItemInfo); GlobalFree(hMemDocInfo); tmpItemFile.Flush(); tmpItemFile.SeekToBegin(); tmpItemFile.Close(); tmpDocFile.Flush(); tmpDocFile.SeekToBegin(); //把项信息原文件压缩为名为strTpf的文件 CString strTpf; strTpf=CreateTempFileName(); CZip zip(strTmpItemFileName); zip.SwapSize(strTpf); DeleteFile(strTmpItemFileName); //删除项信息原文件 CFile tpf; tpf.Open(strTpf,CFile::modeRead|CFile::shareDenyWrite); //写入文件头 CFile file; file.Open(strFileName,CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite); FILE_HEADER *pFHeader; HGLOBAL hMemFHeader=GlobalAlloc(GHND,sizeof(FILE_HEADER)+1); pFHeader=(FILE_HEADER*)GlobalLock(hMemFHeader); GlobalUnlock(hMemFHeader); pFHeader->dwItemCount=m_dwItemCount; pFHeader->dwDocOffset=sizeof(FILE_HEADER)+tpf.GetLength(); pFHeader->dwItemInfoCompressedSize=tpf.GetLength(); strcpy(pFHeader->szFlag,"鲍浩波"); //置文件标志 file.Write(pFHeader,sizeof(FILE_HEADER)); //先写入文件头 GlobalFree(hMemFHeader); //写入已压缩的项信息 LPVOID lpBuffer; HGLOBAL hMemFile=GlobalAlloc(GHND,tpf.GetLength()); lpBuffer=GlobalLock(hMemFile); GlobalUnlock(hMemFile); tpf.ReadHuge(lpBuffer,tpf.GetLength()); file.WriteHuge(lpBuffer,tpf.GetLength()); tpf.Close(); DeleteFile(strTpf); //删除信息临时压缩文件 GlobalFree(hMemFile); //转移tmpDocFile中的内容到主文件中 hMemFile=GlobalAlloc(GHND,tmpDocFile.GetLength()); lpBuffer=GlobalLock(hMemFile); GlobalUnlock(hMemFile); tmpDocFile.ReadHuge(lpBuffer,tmpDocFile.GetLength()); file.WriteHuge(lpBuffer,tmpDocFile.GetLength()); GlobalFree(hMemFile); tmpDocFile.Close(); file.Close(); DeleteFile(strTmpDocFileName); //删除临时文件 return TRUE; } //辅助函数,用于保存文件时获取下一个要保存的项,采用深度优先遍历 HTREEITEM CNoteDlg::GetNextWriteItem(HTREEITEM hItem, int &flag) { if(m_wndTree.ItemHasChildren(hItem)) //有子节点 { flag=-1; return m_wndTree.GetChildItem(hItem); } HTREEITEM hSibItem=m_wndTree.GetNextSiblingItem(hItem); if(hSibItem)// 无子节点,但有兄弟节点,则返回兄弟节点 { flag=0; return hSibItem; } else //既无子节点,也无兄弟节点,则寻找上级节点的兄弟节点 { //flag表示上溯的级数 flag=0; hSibItem=NULL; do{ flag++; hItem=m_wndTree.GetParentItem(hItem); hSibItem=m_wndTree.GetNextSiblingItem(hItem); }while(hSibItem==NULL&&hItem); if(!hItem) return NULL; else return hSibItem; } } //菜单项"打开"的响应函数 void CNoteDlg::OnOpenFile() { // TODO: Add your command handler code here CFileDialog dlgFile(TRUE,"not",NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"笔记本文件(*.not)|*.not|所有文件(*.*)|*.*|"); if(dlgFile.DoModal()==IDOK) { CString strFileName=dlgFile.GetPathName(); if(!CheckFileFormat(strFileName)) return; //格式正确,则提示保存以前更改 if(m_bIsModified) { int res=AfxMessageBox(IDS_SAVE_MODIFY,MB_YESNOCANCEL|MB_ICONQUESTION); if(res==IDCANCEL) return; else if(res==IDYES) SaveModified(); else m_bIsModified=FALSE; } OpenTree(strFileName); //构造树 } } //菜单项"保存为"的响应函数 void CNoteDlg::OnSaveAs() { // TODO: Add your command handler code here if(m_wndTree.GetCount()<=0) return; CFileDialog fileDlg(FALSE,"not",NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"笔记本文件(*.not)|*.not|所有文件(*.*)|*.*|"); if(fileDlg.DoModal()==IDOK) { SaveTree(fileDlg.GetPathName()); OpenTree(fileDlg.GetPathName()); } m_bIsModified=FALSE; } //菜单项"关于"的响应函数 void CNoteDlg::OnAbout() { // TODO: Add your command handler code here CAboutDlg dlg; dlg.DoModal(); } //菜单项"新建"的响应函数,建立新文件 void CNoteDlg::OnNew() { // TODO: Add your command handler code here if(m_bIsModified) { int res=AfxMessageBox(IDS_SAVE_MODIFY,MB_YESNOCANCEL|MB_ICONQUESTION); if(res==IDCANCEL) return; else if(res==IDYES) SaveModified(); else if(res==IDNO) m_bIsModified=FALSE; } Reset(); GetDlgItem(IDC_ADDNEW)->EnableWindow(TRUE); OnAddnew(); } //构造树 //请先参阅所附的<<说明.txt>> BOOL CNoteDlg::OpenTree(CString strFileName) { //把原文件strFileName复制另一份用于填充树以及操作中的读写 Reset(); CString strNewTitle; strNewTitle+=m_strTitle+" - "+strFileName; SetWindowText(strNewTitle); m_strOpenFileName=strFileName; //设置打开文件为strFileName m_strCurOpenFile=CreateTempFileName(); CopyFile(m_strOpenFileName,m_strCurOpenFile,FALSE);//复制文件 //先读出文件头中包含的dwItemCount和dwItemInfoCompressedSize; FILE_HEADER FHeader; CFile file; file.Open(m_strCurOpenFile,CFile::modeRead); file.Read((LPVOID)(&FHeader),sizeof(FILE_HEADER)); CString strTpfName=CreateTempFileName(); CString strTempItemFileName=CreateTempFileName(); //把文件中的ItemInfo压缩信息读到临时文件strTpfName CFile tpf; tpf.Open(strTpfName,CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite); HGLOBAL hMem=GlobalAlloc(GHND,FHeader.dwItemInfoCompressedSize); LPVOID lpBuffer; lpBuffer=GlobalLock(hMem); GlobalUnlock(hMem); file.ReadHuge(lpBuffer,FHeader.dwItemInfoCompressedSize); tpf.WriteHuge(lpBuffer,FHeader.dwItemInfoCompressedSize); tpf.Flush(); file.Close(); tpf.Close(); //解压缩所文件strTpfName到文件strTempItemFileName CUnZip unZip(strTpfName); unZip.SwapSize(strTempItemFileName); DeleteFile(strTpfName); //删除strTpfName CFile itemFile; itemFile.Open(strTempItemFileName,CFile::modeRead|CFile::shareDenyWrite); DWORD dwItemCount=FHeader.dwItemCount;//总的节点项数 //开始读各个Item信息 ITEM_INFO *pItemInfo; UINT size=sizeof(ITEM_INFO); HGLOBAL hMemItemInfo=GlobalAlloc(GHND,size+1); pItemInfo=(ITEM_INFO*)GlobalLock(hMemItemInfo); GlobalUnlock(hMemItemInfo); itemFile.Read(pItemInfo,size); HTREEITEM hItem=TVI_ROOT; hItem=m_wndTree.InsertItem(pItemInfo->szName,hItem); m_wndTree.SetItemData(hItem,m_dwDocCount); m_dwItemCount=1; //已插入了一个节点 while((itemFile.Read(pItemInfo,size)==size)&&m_dwItemCount<dwItemCount) { m_dwItemCount++; if(pItemInfo->nFlag==-1) //表示要插入的节点时前一插入节点的子项 hItem=m_wndTree.InsertItem(pItemInfo->szName,hItem); else if(pItemInfo->nFlag==0)//表示要插入的节点时前一插入节点的兄弟项 { hItem=m_wndTree.GetParentItem(hItem); hItem=m_wndTree.InsertItem(pItemInfo->szName,hItem); } else { for(int i=0;i<=pItemInfo->nFlag;i++) hItem=m_wndTree.GetParentItem(hItem); hItem=m_wndTree.InsertItem(pItemInfo->szName,hItem); } if(pItemInfo->bIsDoc) //如果该项是文档项,则把它的信息添加到队列m_arDoc中 { m_dwDocCount++; //文档项数加1 m_wndTree.SetItemData(hItem,m_dwDocCount); //设置该项data为其在总的文档数中的序数 m_wndTree.SetItemImage(hItem,2,2); DOC_INFO *pDocInfo; HGLOBAL hMemDocInfo=GlobalAlloc(GHND,sizeof(DOC_INFO)+1); pDocInfo=(DOC_INFO*)GlobalLock(hMemDocInfo); GlobalUnlock(hMemDocInfo); pDocInfo->bIsNew=FALSE; strcpy(pDocInfo->szFileName,m_strCurOpenFile);//把其对应的文件名设置为m_strCurOpenFile, pDocInfo->dwOffset=pItemInfo->dwOffset+FHeader.dwDocOffset; pDocInfo->dwLength=pItemInfo->dwLength; pDocInfo->bIsNew=FALSE; m_arDoc.SetAtGrow(m_dwDocCount,*pDocInfo); GlobalFree(hMemDocInfo); } else //不是文档项,则设置ItemData为-1 { m_wndTree.SetItemData(hItem,-1); m_wndTree.SetItemImage(hItem,0,0); } } itemFile.Close(); DeleteFile(strTempItemFileName); GlobalFree(hMemItemInfo); m_wndTree.Expand(m_wndTree.GetRootItem(),TVE_TOGGLE); return TRUE; } //辅助函数,创建临时文件名 CString CNoteDlg::CreateTempFileName() { char szPath[MAX_PATH]; CString strTmpFileName; GetTempPath(MAX_PATH,szPath); GetTempFileName(szPath,"bhb",0,strTmpFileName.GetBuffer(MAX_PATH+1)); strTmpFileName.ReleaseBuffer(); return strTmpFileName; } //树中的被选项发生了变化 void CNoteDlg::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // TODO: Add your control notification handler code here TVITEM tvItem; tvItem=pNMTreeView->itemNew; HTREEITEM hItem; hItem=tvItem.hItem; //获得被选项 if(!hItem) { GetDlgItem(IDC_RENAME)->EnableWindow(FALSE); return; } GetDlgItem(IDC_RENAME)->EnableWindow(); DWORD dwItemData=-1; dwItemData=m_wndTree.GetItemData(hItem); //获得该项的Data if(dwItemData!=-1) //如不是-1,则说明是文档节点 { GetDlgItem(IDC_ADDNEW)->EnableWindow(FALSE); //文档节点下不可添加子节点 GetDlgItem(IDC_DEL)->EnableWindow(TRUE); //只有文档节点和无子节点的类节点可以被删除 DOC_INFO docInfo; docInfo=m_arDoc.GetAt((int)dwItemData); //从队列中获取该文档节点的信息 if(docInfo.dwLength>0) //文档长度大于0 { CFile dataFile; dataFile.Open(docInfo.szFileName,CFile::modeRead); LPVOID lpBuffer; HGLOBAL hMem=GlobalAlloc(GHND,docInfo.dwLength); lpBuffer=GlobalLock(hMem); dataFile.Seek(docInfo.dwOffset,CFile::begin); dataFile.Read(lpBuffer,docInfo.dwLength); //读出文档内容 GlobalUnlock(hMem); dataFile.Close(); //如果节点信息中的文件名不是m_strCupOpenFile,则说明不是压缩数据,可以直接填充编辑控件 if(m_strCurOpenFile.CompareNoCase(docInfo.szFileName)) { m_wndOwnEdit.SetWindowText((LPCTSTR)lpBuffer); GlobalFree(hMem); } else //是压缩数据,则把压缩数据写到临时文件tmpFile1中 { CString tmpFile1; tmpFile1=CreateTempFileName(); CFile fl; fl.Open(tmpFile1,CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite); fl.Write(lpBuffer,docInfo.dwLength); fl.Flush(); fl.Close(); CString tmpFile2; tmpFile2=CreateTempFileName(); CUnZip unZip(tmpFile1); unZip.SwapSize(tmpFile2); //把压缩数据解压到tmpFile2中 DeleteFile(tmpFile1); fl.Open(tmpFile2,CFile::modeRead|CFile::shareDenyWrite); DWORD length; length=fl.GetLength(); GlobalFree(hMem); hMem=GlobalAlloc(GHND,length); lpBuffer=GlobalLock(hMem); fl.ReadHuge(lpBuffer,length); //读出解压缩后的数据 GlobalUnlock(hMem); fl.Close(); m_wndOwnEdit.SetWindowText((LPCTSTR)lpBuffer); //填充编辑控件 GlobalFree(hMem); //重新设置该文档节点的信息 docInfo.bIsNew=FALSE; docInfo.dwLength=length; docInfo.dwOffset=0; strcpy(docInfo.szFileName,tmpFile2); //重定向文档节点的对应文件名,下次显示该节点内容时就不必再解压缩 m_arDoc.SetAt((int)dwItemData,docInfo); } } } else //如果不是文档节点,而是类节点 { m_wndOwnEdit.SetWindowText(""); GetDlgItem(IDC_ADDNEW)->EnableWindow(); //可以添加子节点 if(m_wndTree.ItemHasChildren(hItem)) GetDlgItem(IDC_DEL)->EnableWindow(FALSE); else GetDlgItem(IDC_DEL)->EnableWindow(TRUE); } *pResult = 0; } //重载IDCANCEL的响应函数,防止用户按下ESC后窗口关闭 void CNoteDlg::OnCancel() { // TODO: Add extra cleanup here return; CDialog::OnCancel(); } //重载IDOK的响应函数,防止用户按下回车后窗口关闭 void CNoteDlg::OnOk() { // TODO: Add your control notification handler code here return; } //用户单击了窗口右上角的关闭按钮. void CNoteDlg::OnClose() { // TODO: Add your message handler code here and/or call default if(m_bIsModified) { int res=AfxMessageBox(IDS_SAVE_MODIFY,MB_YESNOCANCEL|MB_ICONQUESTION); if(res==IDCANCEL) return; else if(res==IDYES) SaveModified(); } // 删除临时文件 CFileFind finder; if(!m_strCurOpenFile.IsEmpty()) { if(finder.FindFile(m_strCurOpenFile)) DeleteFile(m_strCurOpenFile); finder.Close(); m_strCurOpenFile.Empty(); } //删除各个文档节点对应的临时文件 int upper; upper=m_arDoc.GetUpperBound(); if(upper>-1) { DOC_INFO docInfo; for(int i=0;i<=upper;i++) { docInfo=m_arDoc.GetAt(i); if(finder.FindFile(docInfo.szFileName)) { DeleteFile(docInfo.szFileName); finder.Close(); } } m_arDoc.RemoveAll(); //清除队列 } CDialog::OnClose(); CDialog::OnOK(); } //菜单项"退出"的响应函数 void CNoteDlg::OnExit() { // TODO: Add your command handler code here OnClose(); } //该函数处理用那种方式保存 void CNoteDlg::SaveModified() { if(m_wndTree.GetCount()>0) { if(m_strCurOpenFile.IsEmpty()) OnSaveAs(); else OnSave(); } } //菜单项"保存"的响应函数 void CNoteDlg::OnSave() { // TODO: Add your command handler code here if(m_bIsModified==FALSE) return; //如果当前打开文件名为空,说明是建的文件,则调用OnSaveAs()函数 if(m_strOpenFileName.IsEmpty()) { OnSaveAs(); return; } else { SaveTree(m_strOpenFileName); //保存完后重新打开新文件,在OpenTree中调用了Reset()函数 OpenTree(m_strOpenFileName); m_bIsModified=FALSE; } } //按钮"删除"的响应函数,删除树中的节点 void CNoteDlg::OnDel() { // TODO: Add your control notification handler code here HTREEITEM hItem; hItem=m_wndTree.GetSelectedItem(); HTREEITEM hParentItem; hParentItem=m_wndTree.GetParentItem(hItem); if(hItem) { m_wndTree.DeleteItem(hItem); m_dwItemCount--; if(m_wndTree.GetCount()<=0) if(m_strCurOpenFile.IsEmpty()) { m_bIsModified=FALSE; return; } if(hParentItem) if(!m_wndTree.ItemHasChildren(hParentItem)) m_wndTree.SetItemImage(hParentItem,0,0); m_bIsModified=TRUE; } } //按钮"更名"的响应函数 void CNoteDlg::OnRename() { // TODO: Add your control notification handler code here HTREEITEM hItem; hItem=m_wndTree.GetSelectedItem(); if(hItem) { CString strOldName=m_wndTree.GetItemText(hItem);; CChangeNameDlg dlg; dlg.m_strNewName=dlg.m_strOldName=strOldName; if(dlg.DoModal()==IDOK) { if(dlg.m_strNewName.CompareNoCase(strOldName)) m_wndTree.SetItemText(hItem,dlg.m_strNewName); m_bIsModified=TRUE; } } } void CNoteDlg::Reset() { m_wndOwnEdit.SetWindowText(""); SetWindowText(m_strTitle); //恢复窗口标题 m_wndTree.DeleteAllItems(); //删除树中的所有项的 m_dwDocCount=-1; m_dwItemCount=0; m_strOpenFileName.Empty(); // 删除临时文件 CFileFind finder; if(!m_strCurOpenFile.IsEmpty()) { if(finder.FindFile(m_strCurOpenFile)) DeleteFile(m_strCurOpenFile); finder.Close(); m_strCurOpenFile.Empty(); } //删除各个文档节点对应的临时文件 int upper; upper=m_arDoc.GetUpperBound(); if(upper>-1) { DOC_INFO docInfo; for(int i=0;i<=upper;i++) { docInfo=m_arDoc.GetAt(i); if(finder.FindFile(docInfo.szFileName)) { DeleteFile(docInfo.szFileName); finder.Close(); } } m_arDoc.RemoveAll(); //清除队列 } } void CNoteDlg::OnDestroy() { CDialog::OnDestroy(); // TODO: Add your message handler code here m_wndOwnEdit.DestroyWindow(); //销毁创建的编辑控件 delete m_pImgList; //释放内存空间 delete m_pEditFont; } void CNoteDlg::OnItemexpandedTree(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // TODO: Add your control notification handler code here TVITEM tvItem; tvItem=pNMTreeView->itemNew; HTREEITEM hItem; hItem=tvItem.hItem; if(!hItem) return; if(pNMTreeView->action==2) m_wndTree.SetItemImage(hItem,1,1); else if(pNMTreeView->action==1) m_wndTree.SetItemImage(hItem,0,0); *pResult = 0; } //辅助函数,检查文件格式 BOOL CNoteDlg::CheckFileFormat(CString strFileName) { CFile file; if(!file.Open(strFileName,CFile::modeRead)) { AfxMessageBox(AFX_IDP_FAILED_TO_LAUNCH); return FALSE; } FILE_HEADER fileHeader; if(file.Read(&fileHeader,sizeof(FILE_HEADER))!=sizeof(FILE_HEADER)) { AfxMessageBox(IDS_ERROR_FORMAT,MB_ICONEXCLAMATION|MB_OK); file.Close(); return FALSE; } if(strcmp(fileHeader.szFlag,"鲍浩波")!=0) { AfxMessageBox(IDS_ERROR_FORMAT,MB_ICONEXCLAMATION|MB_OK); file.Close(); return FALSE; } file.Close(); return TRUE; } //设置文档内容显示框的字体. void CNoteDlg::OnFont() { // TODO: Add your command handler code here LOGFONT lf; m_wndOwnEdit.GetFont()->GetLogFont(&lf); CFontDialog fontDlg(&lf, CF_SCREENFONTS); if(fontDlg.DoModal()==IDOK) { fontDlg.GetCurrentFont(&lf); m_pEditFont->Detach(); m_pEditFont->CreateFontIndirect(&lf); m_wndOwnEdit.SetFont(m_pEditFont); } }